package com.company.cloud.behavior.client;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.company.cloud.behavior.modules.api.response.*;
import com.company.cloud.behavior.modules.base.entity.UserCommentInfo;
import com.company.cloud.behavior.modules.base.service.*;
import com.company.cloud.behavior.modules.cache.utils.BehaviorConvertUtils;
import com.company.cloud.common.asserts.ValidatorUtils;
import com.company.cloud.common.bean.BaseClientResult;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.utils.CheckUtils;
import com.company.cloud.user.modules.api.response.UserSimple;
import com.company.cloud.user.modules.api.service.UserRemoteService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.company.cloud.behavior.modules.api.service.BehaviorClientService;
import com.company.cloud.behavior.modules.base.entity.UserCollectionInfo;
import com.company.cloud.behavior.modules.base.entity.UserFollowInfo;
import com.company.cloud.behavior.modules.base.entity.UserThumbsUpInfo;
import com.company.cloud.behavior.modules.cache.service.BehaviorCacheService;
import com.company.cloud.common.constant.BaseConstant;

@Log4j2
@RestController
@Service
public class BehaviorClientServiceImpl implements BehaviorClientService {
    @Autowired
    private UserCollectionInfoService userCollectionInfoService;

    @Autowired
    private BehaviorCacheService behaviorCacheService;

    @Autowired
    private UserFollowInfoService userFollowInfoService;

    @Autowired
    private UserThumbsUpInfoService userThumbsUpInfoService;

    @Autowired
    private UserRemoteService userRemoteService;

    @Autowired
    private UserCommentInfoService userCommentInfoService;

    @Override
    public BaseClientResult<CollectionSearchModel> getCollectionInfo(BehaviorSearchParam param) {
        try {
            ValidatorUtils.validate(param);
            CollectionSearchModel model = new CollectionSearchModel();
            if (CheckUtils.hasInt(param.getUserId())) {
                UserCollectionInfo info = userCollectionInfoService.getOne(
                        new QueryWrapper<UserCollectionInfo>()
                                .eq("user_id", param.getUserId())
                                .eq("obj_type", param.getObjType())
                                .eq("obj_no", param.getObjNo())
                                .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
                );
                if (info != null) {
                    model.setIsCollected(BaseConstant.YNEnum.YES.getCode());
                    model.setCollectId(info.getId());
                }
            }
            model.setCount(behaviorCacheService.getCollectionCount(param.getObjType(), param.getObjNo()));
            return BaseClientResult.success(model);
        } catch(Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<List<CollectionSearchModel>> getCollectionList(BehaviorSearchListParam param) {
        try {
            ValidatorUtils.validate(param);
            List<CollectionSearchModel> result = new ArrayList<CollectionSearchModel>();
            if (CheckUtils.hasInt(param.getUserId())) {
                List<UserCollectionInfo> list = userCollectionInfoService.list(
                        new QueryWrapper<UserCollectionInfo>()
                                .eq("user_id", param.getUserId())
                                .eq("obj_type", param.getObjType())
                                .in("obj_no", param.getObjNo())
                                .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
                );
                // list2map
                Map<String, UserCollectionInfo> map = list.stream().collect(Collectors.toMap(item -> item.getObjNo(), item -> item));
                for(String objNo : param.getObjNo()){
                    CollectionSearchModel model = new CollectionSearchModel();
                    model.setCount(behaviorCacheService.getCollectionCount(param.getObjType(), objNo));
                    if (map.containsKey(objNo)) {
                        model.setIsCollected(BaseConstant.YNEnum.YES.getCode());
                        model.setCollectId(map.get(objNo).getId());
                    }
                    result.add(model);
                }
            } else {
                for(String objNo : param.getObjNo()){
                    CollectionSearchModel model = new CollectionSearchModel();
                    model.setCount(behaviorCacheService.getCollectionCount(param.getObjType(), objNo));
                    result.add(model);
                }
            }
            return BaseClientResult.success(result);
        } catch(Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<Integer> getCommentInfo(BehaviorSearchParam param) {
        try {
            ValidatorUtils.validate(param);
            Integer num= behaviorCacheService.getCommentCount(param.getObjType(), param.getObjNo());
            return BaseClientResult.success(num);
        } catch(Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<CommentSearchModel> getCommentUserInfo(BehaviorSearchParam param) {
        try {
            ValidatorUtils.validate(param);
            CommentSearchModel model = new CommentSearchModel();
            model.setCount(behaviorCacheService.getCommentCount(param.getObjType(), param.getObjNo()));
            List<UserCommentInfo> commentList = userCommentInfoService.list(
                    new QueryWrapper<UserCommentInfo>()
                            .eq("obj_type", param.getObjType())
                            .eq("obj_no", param.getObjNo())
                            .eq("parent_id", 0)
                            .orderByDesc("comment_time")
                            .last("limit 5 ")
            );
            Set<Integer> userIds=new HashSet<Integer>();
            commentList.forEach(comment->{
                userIds.add(comment.getUserId());
            });
            BaseClientResult<Map<Integer, UserSimple>> userMapResp = userRemoteService.getUserMapByIds(userIds);


            if (CheckUtils.hasClientResult(userMapResp)) {
                List<CommentModel> comments = new ArrayList<>();
                commentList.forEach(comment->{
                    comments.add(BehaviorConvertUtils.getCommentModel(comment, userMapResp.getData()));
                });
                model.setComments(comments);
                return BaseClientResult.success(model);
            } else {
                return BaseClientResult.error(userMapResp.getCode(),userMapResp.getMsg());
            }
        } catch(Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<List<Integer>> getCommentList(BehaviorSearchListParam param) {
        try {
            ValidatorUtils.validate(param);
            List<Integer> result = new ArrayList<Integer>();
            for(String objNo : param.getObjNo()) {
                result.add(behaviorCacheService.getCommentCount(param.getObjType(), objNo));
            }
            return BaseClientResult.success(result);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<FollowSearchModel> getFollowInfo(BehaviorSearchParam param) {
        try {
            ValidatorUtils.validate(param);
            FollowSearchModel model = new FollowSearchModel(param.getObjType(),param.getObjNo());
            if (CheckUtils.hasInt(param.getUserId())) {
                UserFollowInfo info = userFollowInfoService.getOne(
                        new QueryWrapper<UserFollowInfo>()
                                .eq("user_id", param.getUserId())
                                .eq("obj_type", param.getObjType())
                                .in("obj_no", param.getObjNo())
                                .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
                );
                if (info != null) {
                    model.setIsFollowed(BaseConstant.YNEnum.YES.getCode());
                    model.setFollowId(info.getId());
                }
            }
            model.setCount(behaviorCacheService.getFollowCount(param.getObjType(), param.getObjNo()));
            return BaseClientResult.success(model);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }


    /**获取对象的关注情况(Map)*/
    @Override
    public BaseClientResult<Map<String,FollowSearchModel>> getFollowMap(@RequestBody BehaviorSearchListParam param){
        try {
            List<FollowSearchModel> list= this._getFollowList(param);
            Map<String,FollowSearchModel> data=new HashMap<>();
            if(!CollectionUtils.isEmpty(list)){
                list.forEach(item->{
                    data.put(item.getObjNo(),item);
                });
            }
            return BaseClientResult.success(data);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    private List<FollowSearchModel> _getFollowList(BehaviorSearchListParam param) {
        ValidatorUtils.validate(param);
        List<FollowSearchModel> result = new ArrayList<FollowSearchModel>();
        if (CheckUtils.hasInt(param.getUserId())) {
            List<UserFollowInfo> list = userFollowInfoService.list(
                    new QueryWrapper<UserFollowInfo>()
                            .eq("user_id", param.getUserId())
                            .eq("obj_type", param.getObjType())
                            .in("obj_no", param.getObjNo())
                            .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
            );
            Map<String, UserFollowInfo> map = list.stream().collect(
                    Collectors.toMap(item -> item.getObjNo(), item -> item));
            for(String objNo : param.getObjNo()){
                FollowSearchModel model = new FollowSearchModel(param.getObjType(),objNo);
                model.setCount(behaviorCacheService.getFollowCount(param.getObjType(), objNo));
                if (map.containsKey(objNo)) {
                    model.setIsFollowed(BaseConstant.YNEnum.YES.getCode());
                    model.setFollowId(map.get(objNo).getId());
                }
                result.add(model);
            }
        } else {
            for(String objNo : param.getObjNo()) {
                FollowSearchModel model = new FollowSearchModel(param.getObjType(),objNo);
                model.setCount(behaviorCacheService.getFollowCount(param.getObjType(), objNo));
                result.add(model);
            }
        }
        return result;
    }


    @Override
    public BaseClientResult<List<FollowSearchModel>> getFollowList(BehaviorSearchListParam param) {
        try {
            List<FollowSearchModel> result= this._getFollowList(param);
            return BaseClientResult.success(result);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<ThumbsUpSearchModel> getThumbsUpInfo(BehaviorSearchParam param) {
        try {
            ValidatorUtils.validate(param);
            ThumbsUpSearchModel model = new ThumbsUpSearchModel();
            if (CheckUtils.hasInt(param.getUserId())) {
                UserThumbsUpInfo info = userThumbsUpInfoService.getOne(
                        new QueryWrapper<UserThumbsUpInfo>()
                                .eq("user_id", param.getUserId())
                                .eq("obj_type", param.getObjType())
                                .eq("obj_no", param.getObjNo())
                                .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())

                );
                model.setCount(behaviorCacheService.getThumbsUpCount(param.getObjType(), param.getObjNo()));
                if (info != null) {
                    model.setIsThumbsUp(BaseConstant.YNEnum.YES.getCode());
                    model.setThumbsUpId(info.getId());
                }
            }
            model.setCount(behaviorCacheService.getThumbsUpCount(param.getObjType(), param.getObjNo()));
            return BaseClientResult.success(model);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<ThumbsUpSearchModel> getThumbsUpUserInfo(BehaviorSearchParam param) {
        try {
            BaseClientResult<ThumbsUpSearchModel> modelResp = getThumbsUpInfo(param);
            if (!BaseReturnEnum.SUCCESS.getCode().equals(modelResp.getCode())) {
                return BaseClientResult.error(modelResp.getCode(), modelResp.getMsg());
            }
            ThumbsUpSearchModel model = modelResp.getData();
            List<UserThumbsUpInfo> list = userThumbsUpInfoService.list(
                    new QueryWrapper<UserThumbsUpInfo>()
                            .eq("obj_type", param.getObjType())
                            .eq("obj_no", param.getObjNo())
                            .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
            );
            Set<Integer> ids = new HashSet<Integer>();
            List<UserSimpleForBehavior> thumbsUpUsers = new ArrayList<>();
            for (UserThumbsUpInfo info: list) {
                ids.add(info.getUserId());
                if (CheckUtils.hasInt(param.getUserTop()) && ids.size() >= param.getUserTop()) {
                    break;
                }
            }
            BaseClientResult<List<UserSimple>> userSimpleList = userRemoteService.getUserListByIds(ids);

            if(!CheckUtils.hasClientResult(userSimpleList)){
                return BaseClientResult.error(userSimpleList.getCode(), userSimpleList.getMsg());
            }
            if (!CollectionUtils.isEmpty(userSimpleList.getData())) {
                userSimpleList.getData().forEach(userSimple->{
                    UserSimpleForBehavior userSimpleForBehavior = new UserSimpleForBehavior();
                    BeanUtils.copyProperties(userSimple,userSimpleForBehavior);
                    thumbsUpUsers.add(userSimpleForBehavior);
                });
            }
            model.setThumbsUpUsers(thumbsUpUsers);
            return BaseClientResult.success(model);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<List<ThumbsUpSearchModel>> getThumbsUpList(BehaviorSearchListParam param) {
        try {
            ValidatorUtils.validate(param);
            List<ThumbsUpSearchModel> result = new ArrayList<ThumbsUpSearchModel>();
            if (CheckUtils.hasInt(param.getUserId())) {
                List<UserThumbsUpInfo> list = userThumbsUpInfoService.list(
                        new QueryWrapper<UserThumbsUpInfo>()
                                .eq("user_id", param.getUserId())
                                .eq("obj_type", param.getObjType())
                                .in("obj_no", param.getObjNo())
                                .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
                );
                Map<String, UserThumbsUpInfo> map = list.stream().collect(Collectors.toMap(item -> item.getObjNo(), item -> item));
                for(String objNo : param.getObjNo()){
                    ThumbsUpSearchModel model = new ThumbsUpSearchModel();
                    model.setCount(behaviorCacheService.getThumbsUpCount(param.getObjType(), objNo));
                    if (map.containsKey(objNo)) {
                        model.setIsThumbsUp(BaseConstant.YNEnum.YES.getCode());
                        model.setThumbsUpId(map.get(objNo).getId());
                    }
                    result.add(model);
                }
            } else {
                for(String objNo : param.getObjNo()) {
                    ThumbsUpSearchModel model = new ThumbsUpSearchModel();
                    model.setCount(behaviorCacheService.getThumbsUpCount(param.getObjType(), objNo));
                    result.add(model);
                }
            }
            return BaseClientResult.success(result);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<Map<String, ThumbsUpSearchModel>> thumbsUpMap(BehaviorSearchListParam param) {



        try {
            ValidatorUtils.validate(param);
            Map<String,ThumbsUpSearchModel> result=new HashMap<>();
            if(CollUtil.isEmpty(param.getObjNo())){
                return BaseClientResult.success(result);
            }

            //点赞数统计
            List<Map<String, Object>> numStaticMapList= userThumbsUpInfoService.listMaps(new QueryWrapper<UserThumbsUpInfo>()
                    .select("obj_type as type ","obj_no as no" ,"count(1) as n")
                    .eq("obj_type",param.getObjType())
                    .in("obj_no",param.getObjNo())
                    .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
                    .eq("obj_is_updown", BaseConstant.YNEnum.YES.getCode())
                    .groupBy("obj_type","obj_no")
            );
            if(CollUtil.isNotEmpty(numStaticMapList)){
                numStaticMapList.forEach(item->{
                    Object no_obj= item.get("no");
                    Object n_obj= item.get("n");
                    if(no_obj!=null && n_obj!=null){
                        String no_str= Convert.toStr(no_obj);
                        Integer n_int=Convert.toInt(n_obj);
                        result.put(no_str,new ThumbsUpSearchModel(n_int));
                    }
                });
            }


            //用户点赞数统计
            if(CheckUtils.hasInt(param.getUserId())){
                List<Map<String, Object>> userNumStaticMapList= userThumbsUpInfoService.listMaps(new QueryWrapper<UserThumbsUpInfo>()
                        .select("obj_type as type ","obj_no as no" ,"count(1) as n")
                        .eq("obj_type",param.getObjType())
                        .in("obj_no",param.getObjNo())
                        .eq("user_id",param.getUserId())
                        .eq("rows_state", BaseConstant.EnabledEnum.ENABLED.getCode())
                        .eq("obj_is_updown", BaseConstant.YNEnum.YES.getCode())
                        .groupBy("obj_type","obj_no")
                );

                if(CollUtil.isNotEmpty(userNumStaticMapList)){
                    userNumStaticMapList.forEach(item->{
                        Object no_obj= item.get("no");
                        Object n_obj= item.get("n");
                        if(no_obj!=null && n_obj!=null){
                            String no_str= Convert.toStr(no_obj);
                            Integer n_int=Convert.toInt(n_obj);
                            ThumbsUpSearchModel  tusm =result.get(no_str);
                            if(tusm!=null){
                                tusm.setIsThumbsUp(BaseConstant.YNEnum.YES.getCode());
                                result.put(no_str,tusm);
                            }else{
                                tusm=new ThumbsUpSearchModel(n_int);
                                tusm.setIsThumbsUp(BaseConstant.YNEnum.YES.getCode());
                                result.put(no_str,tusm);
                            }
                        }
                    });
                }

            }

            return BaseClientResult.success(result);

        } catch (Exception e) {
            return BaseClientResult.error(e);
        }

    }

    @Override
    public BaseClientResult<BigDecimal> getScoreAvgInfo(BehaviorSearchParam param) {
        try {
            return BaseClientResult.success(behaviorCacheService.getScoreAvgInfo(param.getObjType(), param.getObjNo()));
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<Map<String, BigDecimal>> getScoreAvgList(BehaviorSearchListParam param) {
        try {
            return BaseClientResult.success(behaviorCacheService.getScoreAvgMap(param.getObjType(), param.getObjNo()));
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<UserScoreSearchModel> getUserScoreSearchModel(BehaviorSearchParam param) {
        try {
            return BaseClientResult.success(behaviorCacheService.getUserScoreModel(param.getUserId(), param.getObjType(), param.getObjNo()));
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<BehaviorSearchAllModel> getBehaviorInfo(BehaviorSearchAllParam param) {
        try {
            ValidatorUtils.validate(param);
            BehaviorSearchAllModel model = new BehaviorSearchAllModel();
            if (param.isCollectionFlg()) {
                model.setCollectionSearchModel(getCollectionInfo(param).getData());
            }
            if (param.isCommentFlg()) {
                model.setCommentSearchModel(getCommentUserInfo(param).getData());
            }
            if (param.isFollowFlg()) {
                model.setFollowSearchModel(getFollowInfo(param).getData());
            }
            if (param.isThumbsUpFlg()) {
                model.setThumbsUpSearchModel(getThumbsUpUserInfo(param).getData());
            }
            return BaseClientResult.success(model);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<List<BehaviorSearchAllModel>> getBehaviorList(BehaviorSearchListAllParam param) {
        try {
            ValidatorUtils.validate(param);
            List<BehaviorSearchAllModel> result = new ArrayList<>();
            BehaviorSearchParam pa = new BehaviorSearchParam();
            pa.setUserId(param.getUserId());
            pa.setObjType(param.getObjType());
            pa.setUserTop(param.getUserTop());
            param.getObjNo().forEach(objNo -> {
                pa.setObjNo(objNo);
                BehaviorSearchAllModel model = new BehaviorSearchAllModel();
                if (param.isCollectionFlg()) {
                    model.setCollectionSearchModel(getCollectionInfo(pa).getData());
                }
                if (param.isCommentFlg()) {
                    model.setCommentSearchModel(getCommentUserInfo(pa).getData());
                }
                if (param.isFollowFlg()) {
                    model.setFollowSearchModel(getFollowInfo(pa).getData());
                }
                if (param.isThumbsUpFlg()) {
                    model.setThumbsUpSearchModel(getThumbsUpUserInfo(pa).getData());
                }
                result.add(model);
            });
            return BaseClientResult.success(result);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

    @Override
    public BaseClientResult<Map<String, BehaviorSearchAllModel>> getBehaviorMap(BehaviorSearchListAllParam param) {
        try {
            ValidatorUtils.validate(param);
            Map<String, BehaviorSearchAllModel> result = new HashMap<>();
            BehaviorSearchParam pa = new BehaviorSearchParam();
            pa.setUserId(param.getUserId());
            pa.setObjType(param.getObjType());
            pa.setUserTop(param.getUserTop());
            param.getObjNo().forEach(objNo -> {
                pa.setObjNo(objNo);
                BehaviorSearchAllModel model = new BehaviorSearchAllModel();
                if (param.isCollectionFlg()) {
                    model.setCollectionSearchModel(getCollectionInfo(pa).getData());
                }
                if (param.isCommentFlg()) {
                    model.setCommentSearchModel(getCommentUserInfo(pa).getData());
                }
                if (param.isFollowFlg()) {
                    model.setFollowSearchModel(getFollowInfo(pa).getData());
                }
                if (param.isThumbsUpFlg()) {
                    model.setThumbsUpSearchModel(getThumbsUpUserInfo(pa).getData());
                }
                result.put(objNo,model);
            });
            return BaseClientResult.success(result);
        } catch (Exception e) {
            return BaseClientResult.error(e);
        }
    }

}
